home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
tvalt.exe
/
READ.ME
< prev
next >
Wrap
Text File
|
1992-10-05
|
9KB
|
195 lines
Many times I've heard users requesting a method to use Turbo Vision using
BIOS screen writes instead of the default direct-video access method; an even
LARGER group of users want to use TV in graphics mode. This file contains
the information necessary to implement this.
Graphics users:
Deep down in its guts, TV is optimized for character-based drawing to the
screen; this is obvious from the write methods available in the class TView:
they all convert their arguments into a buffer of unsigned chars whose format
is in [attribute][character] pairs - this is for quick direct-transfer to
video memory. No matter WHAT method is used to convert this information to
graphics-calls type information, the process is not quick. For example: when
a 'blank' view paints itself, it fills a buffer with the space character and
the desired attribute, then it calls one of the write methods to draw this
'line' of data for every line in the view. In graphics mode, all you want to
do is bar(...) to fill in the window. The method I present here tries to
optimize this char-based => graphics-based process, but the speed difference
is still quite noticable.
This file, however, is NOT exclusively devoted to graphics-based TV: its
devoted to using an alternate write method for screen drawing. Whether that
alternate method is BIOS calls, graphics painting, etc is not relevant; I
give an example of both in the code.
To enable an alternative write method requires modification of the TV
source code, and source file TVWRITE.ASM in particular. In this read me file
I will list and explain the assembly changes needed for this file; for those
users who do not have the TV source code I am including USEWRITE.OBJ and
NOWRITE.OBJ - the assembled TVWRITE.ASM (I cannot include the modified
TVWRITE.ASM since that is copyrighted material of Borland International's).
Whether you modify the source itself, or use xxxWRITE.OBJ, I *STRONGLY* urge
you to NOT place this code change in TV.LIB. Instead, just include the new
TVWRITE.ASM (or xxxWRITE.OBJ) in your project that requires the alternate
write method. The difference between NO/USEWRITE.OBJ is in its default
behaviour and is described below.
TVWRITE.ASM has a procedure declared which, in the header files, is:
static void writeView( write_args );
This is the actual procedure that writes to the screen in Turbo Vision: all
other write methods put their data into a write_args format and call
TView::writeView(). So it is here that the fundamental changes to TV must be
made.
The first thing we need is some type of global flag that can enable or
disable this option. Here's what's needed for that: at the top of TVWRITE.ASM
you will see a number of PUBLIC ... statements. After the last PUBLIC
statement and before the first EXTRN statement, add the public declaration
for the variable so that it looks like:
...
PUBLIC @TView@writeStr$qssnxzcuc
; --------------------- NEW -------------------------
PUBLIC _useAltWriteMethod
; ---------------------------------------------------
EXTRN @THWMouse@show$qv : PROC
...
This declares our variable public so that other modules can access it. As
long as you're in this area of the code, there's something else we need to
add. When this flag is non-zero (and the write is being performed to the
screen versus a TGroup buffer), we want to call a function that will perform
the actual screen writing. To call this function we have to give the function
a name, and let TVWRITE.ASM know that its a function that is external to this
module. To do that, add the statement to the end of the list of EXTRN ...
statements, so that it looks like this:
...
EXTRN @TScreen@checkSnow : BYTE
; --------------------- NEW -------------------------
EXTRN @altWriteMethod$qsssnuss : PROC
; ---------------------------------------------------
STRUC Fptr
...
This lets the assembler know that we are going to call the function whose
declaraction is:
void altWriteMethod( short,short, short, ushort *, short );
and to take this name into account when assembling. Now we have a flag name
that is globally accessable, and some external function we can call to
perform a screen write. Next we need to actually declare the flag so as to
allocate memory for it. A few lines below these EXTRN statements you'll see
the directive DATASEG - this directive tells the assembler that the
following lines of data are to be allocated into the default data segment
DGROUP: it is here that we want to allocate our flag. Insert it so that it
looks like:
...
DATASEG
wArgs WriteArgs ?
; --------------------- NEW -------------------------
_useAltWriteMethod DW 1
; ---------------------------------------------------
IFDEF 0; PROTECT
...
Note that the '1' initializes _useAltWriteMethod to 1; this is the TV
equivalent of:
Boolean useAltWriteMethod = True;
The definition of our flag (useAltWriteMethod) is that a value of 0 indicates
that the alternate write method should NOT be use; a non-zero value says to
use the alternative method. By using the above declaration, we are telling
the program to, by default, use the alternative method. If you desire that
the default (startup) action to be to NOT use the alternative method, change
the 1 above to a 0. The included USEWRITE.OBJ has a default of True for
useAltWriteMethod; the included NOWRITE.OBJ has a default of False.
Now we have to change TView::writeView() to use altWriteMethod() to draw
instead of the default method (when useAltWriteMethod <> 0 and writeView() is
drawing to the screen). TView::writeView() does a lot more than just write a
line of char-attr pairs to the screen - it searches through the view
hierarchy and takes into account overlapping windows, shadows, etc. But there
is one point in writeView() when everything has been taken into account, and
the code is ready to write the data to the screen. This is in the vicinity
of label @@50, and this is where we'll make our change. When the program
gets to label @@50, the following conditions hold:
AX = the y coordinate (0-based) on the screen of the line to write to.
BX = the x coordinate (0-based) on the screen where the write starts.
CX = the x coordinate (0-based) on the screen where the write ends.
DX = 0 if the buffer's attributes should be used, non-zero if the
shadowAttr should be used.
SI = the segment of the destination address. If SI =
FP_SEG(TScreen::screenBuffer) then this write is aimed at the screen.
wArgs.Buffer = the buffer start address.
wArgs.Offset = the offset into the buffer to use.
the actual buffer start for BX is at wArgs.Buffer+(BX-wArgs.Offset)
The format that we want altWriteMethod to be in is:
void altWriteMethod( short x, short y, short wid, ushort *buf,
short sflag );
where:
(x,y) is the starting column/row on the screen (0-based),
wid is the number of entries in the buffer to write,
buf is the buffer,
sflag is the shadow flag (0 = use buffer attributes, <>0 = use
shadowAttr declared in TVIEW.CPP.
Here's how to implement the call in TVWRITE.ASM:
...
@@50:
PUSH ES
PUSH DS
PUSH DI
PUSH CX
PUSH AX
; --------------------- NEW -------------------------
; call only if its a screen write (ignore TGroup::buffer writes).
CMP SI, [WORD PTR @Tscreen@screenBuffer+2]
JNE @@55
; call only if useAltWriteMethod <> 0.
TEST [_useAltWriteMethod],0FFFFh
JE @@55
PUSH BX
PUSH DX
PUSH SI
; push sflag argument.
PUSH DX
; push buf's segment.
PUSH [wArgs.Buffer.segm]
; compute and push buf's offset.
MOV SI,BX
SUB SI,[wArgs.Offset]
SHL SI,1
ADD SI,[wArgs.Buffer.offs]
PUSH SI
; compute and push wid.
SUB CX,BX
PUSH CX
; push y.
PUSH AX
; push x.
PUSH BX
; call void altWriteMethod(short,short,short,ushort *,short);
CALL @altWriteMethod$qsssnuss
ADD SP,12
POP SI
POP DX
POP BX
; restore conditions and jump around the screen-writing routines.
MOV ES,SI
JMP @@70
@@55:
; ---------------------------------------------------